use proto::{new_frame, new_min_frame, new_res_frame};
use tokio::io::AsyncWriteExt;

use crate::{AppErr, IoErr};




pub trait ProtoWriter {
    
    async fn write_min_frame(&mut self, ts: u8, seq: u8) -> Result<(), IoErr>;
    async fn write_frame(&mut self, ts: u8, seq: u8, cmd: u16, body: &[u8]) -> Result<(), IoErr>;
    async fn write_res_frame(&mut self, ts: u8, seq: u8, cmd: u16, state: u8, body: &[u8]) -> Result<(), IoErr>;
}


impl <T: AsyncWriteExt + Unpin> ProtoWriter for T {

    async fn write_frame(&mut self, ts: u8, seq: u8, cmd: u16, body: &[u8]) -> Result<(), IoErr> {
        self.write_all(&new_frame(ts, seq, cmd, body)).await
    }

    async fn write_min_frame(&mut self, ts: u8, seq: u8) -> Result<(), IoErr> {
        self.write_all(&new_min_frame(ts, seq)).await
    }

    async fn write_res_frame(&mut self, ts: u8, seq: u8, cmd: u16, state: u8, body: &[u8]) -> Result<(), IoErr> {
        self.write_all(&new_res_frame(ts, seq, cmd, state, body)).await
    }
}


pub trait ProtoWriter2<E: Send + std::error::Error> {
    
    async fn write(&self, buf: Box<[u8]>) -> Result<(), E>;

    async fn write_frame(&self, ts: u8, seq: u8, cmd: u16, body: &[u8]) -> Result<(), E> {
        self.write(new_frame(ts, seq, cmd, body)).await?;
        Ok(())
    }

    async fn write_res_frame(&self, ts: u8, seq: u8, cmd: u16, state: u8, body: &[u8]) -> Result<(), E> {
        self.write(new_res_frame(ts, seq, cmd, state, body)).await?;
        Ok(())
    }
}






